﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;
using Workflows.Components.ETL.Properties;

namespace Workflows.Components.ETL
{
    /// <summary>
    /// 
    /// </summary>
    [Serializable]
    public class GrabDataComponent:WorkflowComponentBase
    {
        #region members
        private GrabDataInstruction _instruction;
        private GrabDataOutput _output;

        public override InstructionBase Instruction
        {
            get { return _instruction; }
            set { _instruction =(GrabDataInstruction) value; }
        }

        public override ResultBase Output
        {
            get { return _output; }
            set { _output = (GrabDataOutput)value; }
        }

        /// <summary></summary>
        public DataProviderType KeyDataProvider
        {
            get
            {
                return this._instruction.KeyDataProvider;
            }
            set
            {
                this._instruction.KeyDataProvider = value;
            }
        }

        /// <summary></summary>
        public string KeyConnStr
        {
            get
            {
                return this._instruction.KeyConnStr;
            }
            set
            {
                this._instruction.KeyConnStr = value;
            }
        }

        /// <summary></summary>
        public string KeySql
        {
            get
            {
                return this._instruction.KeySql;
            }
            set
            {
                this._instruction.KeySql = value;
            }
        }

        /// <summary></summary>
        public DataProviderType SrcDataProvider
        {
            get
            {
                return this._instruction.SrcDataProvider;
            }
            set
            {
                this._instruction.SrcDataProvider = value;
            }
        }

        /// <summary></summary>
        public string SrcConnStr
        {
            get
            {
                return this._instruction.SrcConnStr;
            }
            set
            {
                this._instruction.SrcConnStr = value;
            }
        }

        /// <summary></summary>
        public string SrcDataSql
        {
            get
            {
                return this._instruction.SrcDataSql;
            }
            set
            {
                this._instruction.SrcDataSql = value;
            }
        }

        /// <summary></summary>
        public DataProviderType TgtDataProvider
        {
            get
            {
                return this._instruction.TgtDataProvider;
            }
            set
            {
                this._instruction.TgtDataProvider = value;
            }
        }

        /// <summary></summary>
        public string TgtConnStr
        {
            get
            {
                return this._instruction.TgtConnStr;
            }
            set
            {
                this._instruction.TgtConnStr = value;
            }
        }

        /// <summary></summary>
        public string TgtTableName
        {
            get
            {
                return this._instruction.TgtTableName;
            }
            set
            {
                this._instruction.TgtTableName = value;
            }
        }

        /// <summary></summary>
        public List<GrabDataFieldMapping> FieldMappings
        {
            get
            {
                return this._instruction.FieldMappings;
            }
            set
            {
                this._instruction.FieldMappings = value;
            }
        }

        /// <summary></summary>
        public string NonNullFieldSkipUpdate
        {
            get
            {
                return this._instruction.NonNullFieldSkipUpdate;
            }
            set
            {
                this._instruction.NonNullFieldSkipUpdate = value;
            }
        }

        /// <summary></summary>
        public string LogFilePath
        {
            get
            {
                return this._instruction.LogFilePath;
            }
            set
            {
                this._instruction.LogFilePath = value;
            }
        }

        /// <summary></summary>
        public string ErrorFilePath
        {
            get
            {
                return this._instruction.ErrorFilePath;
            }
            set
            {
                this._instruction.ErrorFilePath = value;
            }
        }

        /// <summary></summary>
        public bool UseBcp
        {
            get
            {
                return this._instruction.UseBcp;
            }
            set
            {
                this._instruction.UseBcp = value;
            }
        }
        #endregion

        /// <summary>
        /// ctor
        /// </summary>
        public GrabDataComponent():base()
        {
            this.ComponentActivityType = WorkflowActivityType.SimpleActivity;
            this.ComponentCategory = WorkflowComponentCategory.ETL.ToString();
            this.Description = "Retrieve data by selected key values";
            this.ComponentIcon = Resources.dtspipeline_2_106;
            this.ComponentImage = Resources.transfer2;
            this.ComponentName = "Grab Data";

            this._instruction =
                new GrabDataInstruction(this.ComponentID, Guid.Empty, DataProviderType.MSSQL, string.Empty, string.Empty,
                                        DataProviderType.Oracle, string.Empty, string.Empty, DataProviderType.MSSQL,
                                        string.Empty, string.Empty, string.Empty, null, false, string.Empty, string.Empty);
            this._output = new GrabDataOutput(this.ComponentID, Guid.Empty, 0, string.Empty, string.Empty);
        }

        public override XmlNode Serialize(ref XmlDocument xDoc, ref XmlNode parentNode)
        {
            XmlNode xNode = base.Serialize(ref xDoc, ref parentNode);

            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeyDataProvider", ((int)this.KeyDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeyConnectionStr", this.KeyConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "KeySql", this.KeySql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDataProvider", ((int)this.SrcDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcConnectionStr", this.SrcConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "SrcDataSql", this.SrcDataSql);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtDataProvider", ((int)this.TgtDataProvider).ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtConnectionStr", this.TgtConnStr);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "TgtTableName", this.TgtTableName);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "NonNullFieldSkipUpdate", this.NonNullFieldSkipUpdate);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "UseBcp",this.UseBcp.ToString());
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "LogFilePath", this.LogFilePath);
            XmlDataUtil.UpdateAttribute(ref xDoc, xNode, "ErrorFilePath", this.ErrorFilePath);

            if (this.FieldMappings != null && this.FieldMappings.Count > 0)
            {
                XmlNode fieldMappingRootNode = XmlDataUtil.AddElement(ref xDoc, xNode, "FieldMappings");
                foreach (GrabDataFieldMapping fieldMapping in this.FieldMappings)
                {
                    XmlNode fieldMappingNode = XmlDataUtil.AddElement(ref xDoc, fieldMappingRootNode, "FieldMapping");
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldMappingNode, "SrcField", fieldMapping.SrcField);
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldMappingNode, "TgtField", fieldMapping.TgtField);
                    XmlDataUtil.UpdateAttribute(ref xDoc, fieldMappingNode, "Action", ((int)fieldMapping.Action).ToString());
                }
            }

            return xNode;
        }

        public override WorkflowComponentBase Instantiate(XmlNode xNode)
        {
            if (xNode.Attributes.GetNamedItem("Type").Value == this.GetType().FullName)
            {
                GrabDataComponent component = base.Instantiate(xNode) as GrabDataComponent;

                component.KeyDataProvider =
                    (DataProviderType)int.Parse(XmlDataUtil.GetAttributeValue(xNode, "KeyDataProvider", ((int)DataProviderType.MSSQL).ToString()));
                component.KeyConnStr = XmlDataUtil.GetAttributeValue(xNode, "KeyConnectionStr", string.Empty);
                component.KeySql = XmlDataUtil.GetAttributeValue(xNode, "KeySql", string.Empty);
                component.SrcDataProvider =
                    (DataProviderType)int.Parse(XmlDataUtil.GetAttributeValue(xNode, "SrcDataProvider", ((int)DataProviderType.Oracle).ToString()));
                component.SrcConnStr = XmlDataUtil.GetAttributeValue(xNode, "SrcConnectionStr", string.Empty);
                component.SrcDataSql = XmlDataUtil.GetAttributeValue(xNode, "SrcDataSql", string.Empty);
                component.TgtDataProvider =
                    (DataProviderType)int.Parse(XmlDataUtil.GetAttributeValue(xNode, "TgtDataProvider", ((int)DataProviderType.MSSQL).ToString()));
                component.TgtConnStr = XmlDataUtil.GetAttributeValue(xNode, "TgtConnectionStr", string.Empty);
                component.TgtTableName = XmlDataUtil.GetAttributeValue(xNode, "TgtTableName", string.Empty);
                component.NonNullFieldSkipUpdate = XmlDataUtil.GetAttributeValue(xNode, "NonNullFieldSkipUpdate", string.Empty);
                component.UseBcp = bool.Parse(XmlDataUtil.GetAttributeValue(xNode, "UseBcp", false.ToString()));
                component.LogFilePath = XmlDataUtil.GetAttributeValue(xNode, "LogFilePath", string.Empty);
                component.ErrorFilePath = XmlDataUtil.GetAttributeValue(xNode, "ErrorFilePath", string.Empty);

                component.FieldMappings = null;
                XmlNodeList fieldMappingNodes = xNode.SelectNodes("FieldMappings/FieldMapping");
                if (fieldMappingNodes != null && fieldMappingNodes.Count > 0)
                {
                    component.FieldMappings = new List<GrabDataFieldMapping>();
                    foreach (XmlNode fieldMappingNode in fieldMappingNodes)
                    {
                        GrabDataFieldMapping fieldMapping = new GrabDataFieldMapping();
                        fieldMapping.SrcField = fieldMappingNode.Attributes.GetNamedItem("SrcField").Value;
                        fieldMapping.TgtField = fieldMappingNode.Attributes.GetNamedItem("TgtField").Value;
                        fieldMapping.Action =
                            (FieldDataPopulationAction)
                            int.Parse(fieldMappingNode.Attributes.GetNamedItem("Action").Value);
                        component.FieldMappings.Add(fieldMapping);
                    }
                }

                return component;
            }
            else
                throw new Exception("Unable to instantiate email: invalid type specified in xml node");
        }
    }
}
